package com.calvin.study.multithread.cas;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReference;

import com.calvin.study.entity.UserEntity;
import com.calvin.study.utils.Print;
import com.calvin.study.utils.ThreadUtil;

public class AtomicTest01 {

	public static void main(String[] args) {

		try {
			// testAtomicInteger01();
			 testAtomicInteger02();
			//testAtomicReference();
			//testAtomicIntegerFieldUpdater();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

//	public final int get() //获取当前的值
//	public final int getAndSet(int newValue) //获取当前的值， 然后设置新的值
//	public final int getAndIncrement() //获取当前的值， 然后自增
//	public final int getAndDecrement() //获取当前的值， 然后自减
//	public final int getAndAdd(int delta) //获取当前的值， 并加上预期的值
//	boolean compareAndSet(int expect, int update) //通过CAS方式设置整数值
	public static void testAtomicInteger01() {
		int temValue = 0;

		AtomicInteger i = new AtomicInteger(0);
		// 取值， 然后设置一个新值
		temValue = i.getAndSet(3);
		// 输出tempvalue:0; i:3
		Print.fo("tempvalue=" + temValue + "; i=" + i.get());
		// 取值， 然后自增
		temValue = i.getAndIncrement();
		// 输出tempvalue:3; i:4
		Print.fo("tempvalue=" + temValue + "; i=" + i.get());
		// 取值， 然后增加5
		temValue = i.getAndAdd(5);
		// 输出tempvalue:4; i:9
		Print.fo("tempvalue=" + temValue + "; i=" + i.get());
		// CAS交换
		boolean flag = i.compareAndSet(9, 100);
		// 输出flag:true; i:100
		Print.fo("flag=" + flag + "; i=" + i.get());
	}

	public static void testAtomicInteger02() throws InterruptedException {
		CountDownLatch latch = new CountDownLatch(ThreadUtil.THREAD_COUNT);
		AtomicInteger ai = new AtomicInteger(0);
		for (int i = 0, len = ThreadUtil.THREAD_COUNT; i < len; i++) {
			ThreadUtil.getMixedTargetThreadPool().submit(() -> {
				for (int j = 0; j < 5; j++) {
					ai.getAndIncrement();
				}
				latch.countDown();
			});
		}
		latch.await();
		Print.tco("累加之和： " + ai.get());
	}

	// public final int get(int i) 获取 index=i 位置元素的值
	// public final int getAndSet(int i, int newValue) 返回index=i位置的当前的值， 并将其设置为新值：
	// newValue
	// public final int getAndIncrement(int i) 获取index=i位置元素的值， 并让该位置的元素自增
	// public final int getAndDecrement(int i) 获取index=i位置元素的值， 并让该位置的元素自减
	// public final int getAndAdd(int delta) 获取index=i位置元素的值， 并加上预期的值
	// boolean compareAndSet(int expect, int update) 如果输入的数值等于预期值，
	// 就以原子方式将位置i的元素值设置为输入值（update）
	// public final void lazySet(int i, int
	// newValue)最终将位置i的元素设置为newValue，lazySet方法可能导致其他线程在之后的一小段时间内还是可以读到旧的值
	public static void testAtomicIntegerArray() {

	}

	// 使用原子引用类型AtomicReference包装了User对象之后， 只能保障User引用的原子操作，
	// 对被包装的User对象的字段值修改时不能保证原子性， 这点要切记。
	public static void testAtomicReference() {
		// 包装的原子对象
		AtomicReference<UserEntity> userRef = new AtomicReference<UserEntity>();
		// 待包装的User对象
		UserEntity user = new UserEntity("1", "张三");
		// 为原子对象设置值
		userRef.set(user);
		Print.tco("userRef is:" + userRef.get());
		// 要使用CAS替换的User对象
		UserEntity updateUser = new UserEntity("2", "李四");
		// 使用CAS替换
		boolean success = userRef.compareAndSet(user, updateUser);
		Print.tco(" cas result is:" + success);
		Print.tco(" after cas,userRef is:" + userRef.get());
	}

	public static void testAtomicIntegerFieldUpdater() {
		// 使用静态方法newUpdater()创建一个更新器updater
		AtomicIntegerFieldUpdater<UserEntity> updater = AtomicIntegerFieldUpdater.newUpdater(UserEntity.class, "age");
		UserEntity user = new UserEntity("1", "张三");
		// 使用属性更新器的getAndIncrement、 getAndAdd增加user的age值
		Print.tco(updater.getAndIncrement(user)); // 1
		Print.tco(updater.getAndAdd(user, 100)); // 101
		// 使用属性更新器的get获取user的age值
		Print.tco(updater.get(user)); // 101
	}

}
